import os
import threading
import queue
import subprocess
from models import Video
from comparison import Comparison


class VideoProcessor:
    def __init__(self, prefs):
        self.prefs = prefs
        self.video_list = []
        self.every_video = []
        self.rejected_videos = []
        self.extension_list = [
            'mp4', 'avi', 'mkv', 'mov', 'wmv', 'flv',
            'webm', 'm4v', 'mpeg', 'mpg', '3gp'
        ]
        self.user_pressed_stop = False
        self.previous_run_folders = ""
        self.previous_run_thumbnails = -1
        self.load_extensions()
        self.save_scenes = False
        self.scene_save_path = None

    def load_extensions(self):
        try:
            with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "extensions.ini"), "r") as file:
                for line in file:
                    if line.startswith(";") or line.strip() == "":
                        continue
                    self.extension_list.extend(line.replace("*.", "").strip().split(" "))
        except FileNotFoundError:
            print("Error: extensions.ini not found. No video file will be searched.")

    def detect_ffmpeg(self):
        try:
            subprocess.run("ffmpeg", shell=True, capture_output=True)
            return True
        except FileNotFoundError:
            print("Error: FFmpeg not found. Download it from https://ffmpeg.org/")
            return False

    def find_duplicates(self, folders_to_search, save_scenes=False, scene_save_path=None):
        self.save_scenes = save_scenes
        self.scene_save_path = scene_save_path

        if not self.extension_list:
            print("Error: No extensions found in extensions.ini. No video file will be searched.")
            return
        if not self.detect_ffmpeg():
            return
        if folders_to_search != self.previous_run_folders or self.prefs._thumbnails != self.previous_run_thumbnails:
            print("\nSearching for videos...")
            self.video_list = []
            self.every_video = []
            # directories = folders_to_search.split(";")
            not_found = []
            for directory in folders_to_search:
                if not directory:
                    continue
                if os.path.exists(directory):
                    self.find_videos(directory)
                else:
                    print(f"Cannot find folder: {os.path.normpath(directory)}")
                    not_found.append(os.path.normpath(directory))
            if not_found:
                print(f"Cannot find folder: {' '.join(not_found)}")
            self.process_videos()
        if len(self.video_list) > 1:
            comparison = Comparison(self.video_list, self.prefs)
            comparison.report_matching_videos()
            self.previous_run_folders = folders_to_search
            self.previous_run_thumbnails = self.prefs._thumbnails

    def find_videos(self, directory):
        for root, _, files in os.walk(directory):
            if self.user_pressed_stop:
                return
            for file in files:
                ext = os.path.splitext(file)[1][1:].lower()
                if ext in self.extension_list:
                    full_path = os.path.join(root, file)
                    if full_path.lower() not in [v.lower() for v in self.every_video]:
                        self.every_video.append(full_path)
                    print(os.path.normpath(full_path))

    def process_videos(self):
        self.prefs._numberOfVideos = len(self.every_video)
        print(f"Found {self.prefs._numberOfVideos} video file(s):")
        if self.prefs._numberOfVideos == 0:
            return

        processed_count = 0
        queue_in = queue.Queue()
        queue_out = queue.Queue()

        # 添加所有视频到处理队列
        for filename in self.every_video:
            queue_in.put(filename)

        # 创建工作线程
        def worker():
            nonlocal processed_count
            while True:
                try:
                    filename = queue_in.get(block=False)
                except queue.Empty:
                    break
                video = Video(self.prefs, filename)
                if self.save_scenes and self.scene_save_path:
                    success = video.process(self.scene_save_path)
                else:
                    success = video.process()
                if success:
                    queue_out.put(video)
                else:
                    self.rejected_videos.append(filename)
                processed_count += 1
                print(f"Processed {processed_count}/{self.prefs._numberOfVideos}: {os.path.basename(filename)}")
                queue_in.task_done()

        # 启动多线程处理
        num_workers = min(8, self.prefs._numberOfVideos)
        threads = []
        for _ in range(num_workers):
            t = threading.Thread(target=worker)
            t.start()
            threads.append(t)

        # 等待所有线程完成
        for t in threads:
            t.join()

        # 收集处理好的视频
        while not queue_out.empty():
            self.video_list.append(queue_out.get())

        self.video_summary()

    def video_summary(self):
        if not self.rejected_videos:
            print(f"{len(self.video_list)} intact video(s) found")
        else:
            print(f"{len(self.video_list)} intact video(s) out of {len(self.every_video)} total")
            print(f"\nThe following {len(self.rejected_videos)} video(s) could not be added due to errors:")
            for filename in self.rejected_videos:
                print(os.path.normpath(filename))
        self.rejected_videos = []
